// package 管理协程执行
package routine

import (
	"sync"
)

// OrderedRoutine 有序协程，可以通过前置WaitGrioup和后置WaitGroup控制协程的执行顺序
type OrderedRoutine struct {

	// Operation 协程的执行方法
	Operation func(args ...interface{})

	// Args 方法参数
	Args []interface{}

	// ForewardWGs 前置WaitGrioup，在执行协程方法前需等待的WaitGrioup（wg.Wait()）
	ForewardWGs []*sync.WaitGroup

	// AfterwardWGs 后置WaitGroup，协程方法执行完后需释放的WaitGrioup（wg.Done()）
	AfterwardWGs []*sync.WaitGroup
}

// OrderedRoutineBatch 有序协程池
type OrderedRoutineBatch struct {

	// orderedRoutines 有序协程数组（首字母为小写，限制只能通过Add（）添加有序协程）
	orderedRoutines []*OrderedRoutine
}

// Execute 批量执行有序协程
//
//	@receiver batch
func (batch *OrderedRoutineBatch) Execute() {
	if len(batch.orderedRoutines) == 0 {
		return
	}

	for i := 0; i < len(batch.orderedRoutines); i++ {

		go func(val int) {
			routine := batch.orderedRoutines[val]

			for _, forewardWG := range routine.ForewardWGs {
				forewardWG.Wait()
			}

			routine.Operation(routine.Args...)

			for _, afterwardWG := range routine.AfterwardWGs {
				afterwardWG.Done()
			}

		}(i)
	}
}

// Add 添加有序协程
//
//	@receiver batch 协程批
//	@param routine 有序协程
//	@return *RoutineBatch 添加后的协程批
func (batch *OrderedRoutineBatch) Add(routine *OrderedRoutine) *OrderedRoutineBatch {
	batch.orderedRoutines = append(batch.orderedRoutines, routine)

	for _, afterwardWG := range routine.AfterwardWGs {
		afterwardWG.Add(1)
	}

	return batch
}
